package com.lab.idea.bl.pool;

import cn.hutool.core.thread.NamedThreadFactory;
import cn.hutool.json.JSONObject;
import com.lab.idea.mybatis.util.BeanCopy;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 任务线程池
 * @author mao
 * 核心参数
 * corePoolSize 核心线程数量，是线程池中的一个最小的线程数量，即使这些线程处理空闲状态，他们也不会被销毁，除非设置了allowCoreThreadTimeOut。
 * maximumPoolSize 最大线程数量，任务被提交到线程池以后，首先会找有没有空闲并且存活线程，如果有则直接将任务交给这个空闲线程来执行，如果没有则会放到工作队列中，直到工作队列满了，才会创建一个新线程。
 * keepAliveTime  当线程空闲时间达到keepAliveTime值时,多余的线程会被销毁直到只剩下corePoolSize个线程为止，如果设置了allowCoreThreadTimeOut，核心线程池也会被销毁。
 * 若任务队列已满，并且已经达到最大队列时，走拒绝策略。
 */
@Slf4j
public class LabThreadPoolExecutor extends ThreadPoolExecutor{
    /**
     * 任务队列
     */
    private LabThreadPool threadPool;

    public LabThreadPoolExecutor(LabThreadPool threadPool) {
        super(threadPool.getCorePoolSize(), threadPool.getMaxPoolSize(), threadPool.getKeepAliveTime(),
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(threadPool.getQueueSize()),
                new NamedThreadFactory(threadPool.getPoolName(), false),new AbortPolicy());
        allowCoreThreadTimeOut(true);
        this.threadPool = threadPool;
    }

    /**
     * 更新线程池
     * @param threadPool     队列
     */
    public void update(LabThreadPool threadPool){
        BeanCopy.copy(threadPool,this.threadPool);
        this.setCorePoolSize(threadPool.getCorePoolSize());
        this.setMaximumPoolSize(threadPool.getMaxPoolSize());
        this.setKeepAliveTime(threadPool.getKeepAliveTime(), TimeUnit.SECONDS);
    }

    /**
     * 返回当前线程池状态
     * @return 状态
     */
    public JSONObject getStatus(){
        JSONObject object = new JSONObject();
        object.set("name",this.threadPool.getPoolName());
        object.set("corePoolSize",getCorePoolSize());
        object.set("maximumPoolSize",getMaximumPoolSize());
        object.set("queueSize",getQueue().size());
        object.set("activeCount",getActiveCount());
        object.set("taskCount",getTaskCount());
        object.set("completedTaskCount",getCompletedTaskCount());
        return object;
    }

    public LabThreadPool getTaskQueue() {
        return this.threadPool;
    }

    @Override
    public void shutdown() {
        this.threadPool = null;
        super.shutdown();
    }
}
